﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.SqlClient;

using Fuse8.DomainFramework.Common;
using Fuse8.DomainFramework.DataAccess.SqlDatabase;

using Fuse8.ContentManagementFramework.Domain;

namespace Fuse8.ContentManagementFramework.DataAccess.SqlAccess.Mappers
{
    public class CmsEntityAnnotationContainerDataMapper : BaseSqlEntityDataMapper<CmsEntityAnnotationContainer, int>
    {
        public override CmsEntityAnnotationContainer MapFromMulti(string sp, SqlDataReader reader, CmsEntityAnnotationContainer stepEntity, int index)
        {
            Guard.ArgumentNotEmpty(sp, "sp");
            Guard.ArgumentNotNull(reader, "reader");

            if (stepEntity == null)
            {
                stepEntity = new CmsEntityAnnotationContainer();
            }

            if (index == 0)
            {
                var stepAnnotation = new CmsEntityAnnotation
                {
                    Id = reader.GetInt32(reader.GetOrdinal("AnnotationId")),
                    EntityId = reader.GetInt32(reader.GetOrdinal("EntityId")),
                    EntityTypeParameter = reader.GetString(reader.GetOrdinal("EntityTypeParameter")),
                    AnnotationText = !reader.IsDBNull(reader.GetOrdinal("AnnotationText")) ?
                       reader.GetString(reader.GetOrdinal("AnnotationText")) :
                       null,
                    X = reader.GetInt32(reader.GetOrdinal("X")),
                    Y = reader.GetInt32(reader.GetOrdinal("Y")),
                    Z = reader.GetInt32(reader.GetOrdinal("Z")),
                    IsMinimized = reader.GetBoolean(reader.GetOrdinal("IsMinimized")),
                    CreatedBy = reader.GetInt32(reader.GetOrdinal("CreatedBy")),
                    DateCreated = reader.GetDateTime(reader.GetOrdinal("DateCreated")),
                    LastUpdatedBy = !reader.IsDBNull(reader.GetOrdinal("LastUpdatedBy")) ?
                        reader.GetInt32(reader.GetOrdinal("LastUpdatedBy")) :
                        new Nullable<int>(),
                    DateLastUpdated = !reader.IsDBNull(reader.GetOrdinal("DateLastUpdated")) ?
                       reader.GetDateTime(reader.GetOrdinal("DateLastUpdated")) :
                       new Nullable<DateTime>(),
                    UserCreatedBy = !reader.IsDBNull(reader.GetOrdinal("UserCreatedBy")) ?
                      reader.GetString(reader.GetOrdinal("UserCreatedBy")) :
                      null
                };

                if (stepEntity.Annotations == null)
                {
                    stepEntity.Annotations = new CmsEntityAnnotation[] { stepAnnotation };
                }
                else
                {
                    stepEntity.Annotations = stepEntity.Annotations.Concat(new CmsEntityAnnotation[] { stepAnnotation }).ToList();
                }
            }
            else if (index == 1)
            {
                int annotationId = reader.GetInt32(reader.GetOrdinal("AnnotationId"));

                var currentAnnotation = stepEntity.Annotations.FirstOrDefault(p => p.Id == annotationId);

                if (currentAnnotation != null)
                {
                    var stepAnnotationComment = new CmsEntityAnnotationComment
                    {
                        Id = reader.GetInt32(reader.GetOrdinal("AnnotationCommentId")),
                        Annotation = currentAnnotation,
                        CommentText = !reader.IsDBNull(reader.GetOrdinal("CommentText")) ?
                           reader.GetString(reader.GetOrdinal("CommentText")) :
                           null,
                        OrderIndex = reader.GetInt32(reader.GetOrdinal("OrderIndex")),
                        CreatedBy = reader.GetInt32(reader.GetOrdinal("CreatedBy")),
                        DateCreated = reader.GetDateTime(reader.GetOrdinal("DateCreated")),
                        LastUpdatedBy = !reader.IsDBNull(reader.GetOrdinal("LastUpdatedBy")) ?
                            reader.GetInt32(reader.GetOrdinal("LastUpdatedBy")) :
                            new Nullable<int>(),
                        DateLastUpdated = !reader.IsDBNull(reader.GetOrdinal("DateLastUpdated")) ?
                           reader.GetDateTime(reader.GetOrdinal("DateLastUpdated")) :
                           new Nullable<DateTime>(),
                        UserCreatedBy = !reader.IsDBNull(reader.GetOrdinal("UserCreatedBy")) ?
                            reader.GetString(reader.GetOrdinal("UserCreatedBy")) :
                            null
                    };

                    if (currentAnnotation.Comments == null)
                    {
                        currentAnnotation.Comments = new CmsEntityAnnotationComment[] { stepAnnotationComment };
                    }
                    else
                    {
                        currentAnnotation.Comments = currentAnnotation.Comments.Concat(new CmsEntityAnnotationComment[] { stepAnnotationComment }).ToList();
                    }
                }
            }
            else if (index == 2)
            {
                var annotationId = reader.GetInt32(reader.GetOrdinal("AnnotationId"));
                var stepUserGroup = new CmsUserGroup
                {
                    Id = reader.GetInt32(reader.GetOrdinal("UserGroupId")),
                    SiteId = !reader.IsDBNull(reader.GetOrdinal("SiteId")) ?
                        reader.GetInt32(reader.GetOrdinal("SiteId")) :
                        new Nullable<int>(),
                    SiteGroupId = !reader.IsDBNull(reader.GetOrdinal("SiteGroupId")) ?
                        reader.GetInt32(reader.GetOrdinal("SiteGroupId")) :
                        new Nullable<int>(),
                    GroupName = reader.GetString(reader.GetOrdinal("GroupName")),
                    IsEnabled = reader.GetBoolean(reader.GetOrdinal("IsEnabled")),
                    IsSystem = reader.GetBoolean(reader.GetOrdinal("IsSystem")),
                    CreatedBy = reader.GetInt32(reader.GetOrdinal("CreatedBy")),
                    DateCreated = reader.GetDateTime(reader.GetOrdinal("DateCreated")),
                    LastUpdatedBy = !reader.IsDBNull(reader.GetOrdinal("LastUpdatedBy")) ?
                        reader.GetInt32(reader.GetOrdinal("LastUpdatedBy")) :
                        new Nullable<int>(),
                    DateLastUpdated = !reader.IsDBNull(reader.GetOrdinal("DateLastUpdated")) ?
                       reader.GetDateTime(reader.GetOrdinal("DateLastUpdated")) :
                       new Nullable<DateTime>()
                };

                var annotation = stepEntity.Annotations.SingleOrDefault(e => e.Id == annotationId);
                if (annotation != null)
                {
                    if (annotation.UserGroups == null)
                    {
                        annotation.UserGroups = new CmsUserGroup[] { stepUserGroup };
                    }
                    else
                    {
                        annotation.UserGroups = annotation.UserGroups.Concat(new CmsUserGroup[] { stepUserGroup }).ToList();
                    }
                }
            }
            else
            {
                throw new InvalidOperationException(string.Format("Stored procedure {0} can't return more than {1} result", sp, index));
            }

            return stepEntity;
        }
    }
}
